use axum::Json;
use http::HeaderMap;
use serde_json::Value;
use sea_orm::{ query::*, sea_query::{Alias, Expr}, DbErr,  EntityTrait };
use crate::{auth::claims::get_claims, chrono::now_format, code, query, sea_orm::connect};
// 单个 
pub async fn one<E:EntityTrait>( header:HeaderMap, entity:E, id_field:&str, id_value:i32, field:&str, reason:Option<String>) -> Result<Json<Value>, Json<Value>>{
    let conn = connect().await?;
    let table = entity.table_name();
    let claims = get_claims(header)?;
    let user_id = claims.id;
    let name = claims.name.unwrap_or_default();
    let approver_date = now_format(0);

    let stmt = Statement::from_string(
        conn.get_database_backend(),
        if let Some(f) = reason {
            format!("update {} set {}=0, reason='{}', approver='{}', approver_date='{}', update_user={} where {}={}", table, field, f, name, approver_date, user_id, id_field, id_value)
        }else {
            format!("update {} set {}=0, approver='{}', approver_date='{}', update_user={} where {}={}", table, field, name, approver_date, user_id, id_field, id_value)
        },
    );
    let rs= conn.execute(stmt).await;
    code::send_ok(rs)
}
// 多个
pub async fn many<E:EntityTrait>( header:HeaderMap, entity:E, id_field:&str, id_value:Vec<i32>, field:&str, reason:Option<String>) -> Result<Json<Value>, Json<Value>>{
    let conn = connect().await?;
    let claims = get_claims(header)?;
    let user_id = claims.id;
    let name = claims.name.unwrap_or_default();
    let ids = query::utils::vecstr_i32(id_value)?;
    let ids = ids.join(",");
    let approver_date = now_format(0);

    let result: Result<UpdateResult, DbErr> = Update::many(entity)
    .col_expr( Alias::new(field), 0.into())
    .col_expr(Alias::new("reason"), Expr::value(reason))
    .col_expr(Alias::new("approver"), Expr::value(name))
    .col_expr(Alias::new("approver_date"), Expr::value(approver_date))
    .col_expr(Alias::new("update_user"), Expr::value(user_id))
    .filter(Expr::cust(format!("{} in({})", id_field, ids)))
    .exec(&conn).await;
    code::send_ok(result)
}
// 
pub async fn by_id<E:EntityTrait>( header:HeaderMap, entity:E, body:&Value, field:&str) -> Result<Json<Value>, Json<Value>>{
    let id = query::i32(body, "id")?;
    let reason = query::str_op(body, "reason")?;
    one(header, entity, "id", id, field, reason).await
}
pub async fn by_ids<E:EntityTrait>( header:HeaderMap, entity:E, body:&Value, field:&str ) -> Result<Json<Value>, Json<Value>>{
    let id = query::vec_i32_json(body, "id")?;
    let reason = query::str_op(body, "reason")?;
    if id.len() == 1 {
        one(header, entity, "id", id[0], field, reason).await
    }else {
        many(header, entity, "id", id, field, reason).await
    }
}

pub async fn by_field_auto<E:EntityTrait>(header:HeaderMap, entity:E, body:&Value, id_field:&str, field:&str ) -> Result<Json<Value>, Json<Value>>{
    let reason = query::str_op(body, "reason")?;
    if let Some(f) = body[id_field].as_i64() {
        one(header, entity, id_field, f as i32, field, reason).await
    }else{
        if let Some(f) = query::vec_i32_json_op(&body, id_field)? {
            many(header, entity, id_field, f, field, reason).await
        }else{
            Err(code::err_("传递参数不正确"))
        }
    }
}

pub async fn by_id_auto<E:EntityTrait>( header:HeaderMap, entity:E, body:&Value, field:&str ) -> Result<Json<Value>, Json<Value>>{ 
    by_field_auto(header, entity, body, "id", field).await
}